// 日志系统中各个功能的单项测试
// 因为进行了归类，即弄到不同的文件中，所以，作用域会有些不同

// #include "util.hpp"
// #include "level.hpp"
// #include "format.hpp"
// #include "sink.hpp"
// #include "logger.hpp"
// #include "buffer.hpp"
// #include <string.h>
// #include <fstream>

#include "../logsystem/snowdragon.h"

// 测试util.hpp相关操作

// int main()
// {
//     std::cout << snowdragon::Date::nowDate() << std::endl;
//     std::cout << snowdragon::File::getPath("ab/cd/ef/g.txt") << std::endl;
//     std::cout << snowdragon::File::exists("ab/cd/ef/g.txt") << std::endl;
//     snowdragon::File::createDirectory("ab/cd/ef/g.txt");
//     std::cout << snowdragon::File::exists("ab/cd/ef/g.txt") << std::endl;

//     return 0;
// }

// int main()
// {
//     std::cout << mkdir("abc/def/", 0777)<<" errno: "<<errno<<" err str: "<<strerror(errno) << std::endl;

//     return 0;
// }




// 测试level.hpp相关操作

// int main()
// {
//     std::cout << snowdragon::levelToString(snowdragon::Level::UNKNOWN) << std::endl;
//     std::cout << snowdragon::levelToString(snowdragon::Level::DEBUG) << std::endl;
//     std::cout << snowdragon::levelToString(snowdragon::Level::INFO) << std::endl;
//     std::cout << snowdragon::levelToString(snowdragon::Level::WARN) << std::endl;
//     std::cout << snowdragon::levelToString(snowdragon::Level::ERROR) << std::endl;
//     std::cout << snowdragon::levelToString(snowdragon::Level::FATAL) << std::endl;
//     std::cout << snowdragon::levelToString(snowdragon::Level::OFF) << std::endl;

//     return 0;
// }




// 测试format.hpp和sink.hpp相关操作


// 滚动文件以时间为单位，落地测试

enum class TimeGap
{
    SECOND,
    MIN,
    HOUSE,
    DAY
};

class RollFileByTimeSink : public snowdragon::Sink
{
public:
    using ptr = std::shared_ptr<RollFileByTimeSink>;
    RollFileByTimeSink(const std::string& base_file_path_name, TimeGap time_gap)
        :_base_file_path_name(base_file_path_name)
    {
        snowdragon::util::File::createDirectory(snowdragon::util::File::getPath(_base_file_path_name));
        createFile();
        switch(time_gap)
        {
            case TimeGap::SECOND: _time_gap = 1; break;
            case TimeGap::MIN: _time_gap = 60; break;
            case TimeGap::HOUSE: _time_gap = 3600; break;
            case TimeGap::DAY: _time_gap = 3600*24; break;
        }
        _file_time_gap = snowdragon::util::Date::nowDate();
    }
    void log(const char* str, size_t len)
    {
        if(_file_time_gap + _time_gap < snowdragon::util::Date::nowDate())
            createFile();
        _ofs.write(str, len);
        assert(_ofs.good());
        // _file_time_gap = snowdragon::util::Date::nowDate() % _time_gap;
    }
private:
    void createFile()
    {
        _ofs.close();
        _ofs.open(getNewFileName(), std::ios::binary | std::ios::trunc);
        assert(_ofs.is_open());
        _file_time_gap = snowdragon::util::Date::nowDate();     // 记得修改，方便下次操作，否则将一直创建文件
    }
    std::string getNewFileName()            // 封装，更美观些
    {
        std::stringstream ss;
        ss << _base_file_path_name;
        struct tm t;
        time_t now_time = snowdragon::util::Date::nowDate();
        localtime_r(&now_time, &t);
        ss << t.tm_year + 1900;
        ss << t.tm_mon + 1;
        ss << t.tm_mday;
        ss << t.tm_hour;
        ss << t.tm_min;
        ss << t.tm_sec;
        ss << "-";          // 美观
        ss << _file_count++;
        ss << ".log";
        return ss.str();
    }
private:
    std::string _base_file_path_name;       // 基本文件名
    std::ofstream _ofs;                     // 方便操作，不会多次重复关闭与打开
    int _time_gap;                          // 时间间隙
    time_t _file_time_gap;                 // 当前文件时间间隙
    int _file_count = 0;                    // 文件计数器。防止在一秒内多次创建文件，而文件名相同导致创建失败的情况
};

// int main()
// {
//     // std::shared_ptr<snowdragon::Formatter> fmt(new snowdragon::Formatter("ab%%cd[%d{%H:%M:%S][%t][%c][%p][%f:%l]%T%m%n"));
//     std::shared_ptr<snowdragon::Formatter> fmt(new snowdragon::Formatter("ab%%cd[%d{%H:%M:%S}][%t][%c][%p][%f:%l]%T%m%n"));
//     snowdragon::Message msg("test.cc", 66, snowdragon::Level::INFO, "测试format.hpp", "root");
//     // std::cout << fmt->format(msg) << std::endl;
//     std::string str = fmt->format(msg);

//     // snowdragon::Sink::ptr stdSinkP = snowdragon::SinkFactory::createSink<snowdragon::StdOutSink>();
//     // snowdragon::Sink::ptr spfp = snowdragon::SinkFactory::createSink<snowdragon::specificFileSink>("./log/specificFileSink.log");       // 参数要写在()内
//     // snowdragon::Sink::ptr rfp = snowdragon::SinkFactory::createSink<snowdragon::RollFileBySizeSink>("./log/rollFileSink-", 1024*1024);
    
//     // stdSinkP->log(str.c_str(), str.size());
//     // spfp->log(str.c_str(), str.size());
//     // int size = 0;
//     // int count = 0;
//     // while(size < 1027*1027*6)
//     // {
//     //     std::string tmp = str + std::to_string(count++);
//     //     rfp->log(tmp.c_str(), tmp.size());
//     //     size += tmp.size();
//     // }


//     snowdragon::Sink::ptr rfbtp = snowdragon::SinkFactory::createSink<RollFileByTimeSink>("./log/rollFileSink-", TimeGap::SECOND);
    
//     rfbtp->log(str.c_str(), str.size());
//     int size = 0;
//     int count = 0;
//     while(size < 1024*1024*6)
//     {
//         std::string tmp = str + std::to_string(count++);
//         rfbtp->log(tmp.c_str(), tmp.size());
//         size += tmp.size();
//         usleep(10);         // 略停，2秒创建一个文件，滚动
//     }

//     return 0;
// }




// 测试logger.hpp相关操作

// int main()
// {
//     snowdragon::LocalLoggerBuilder llb;
//     // llb.buildLoggerName("synchronous");

//     llb.buildLoggerName("asynchronous");
//     llb.buildLoggerType(snowdragon::Logger::LoggerType::ASYNC_LOGGER);

//     llb.buildLoggerLevel(snowdragon::LogLevel::Level::WARN);
//     llb.buildLoggerSink<snowdragon::StdOutSink>();
//     llb.buildLoggerSink<snowdragon::specificFileSink>("./log/asynchronous_test.log");
//     // std::cout << "llb.build() before" << std::endl;
//     snowdragon::Logger::ptr logger = llb.build();
//     // std::cout << "llb.build() after" << std::endl;

//     logger->debug("test.cc", 167, "测试logger.hpp相关操作");
//     // std::cout << "logger->debug() after" << std::endl;

//     logger->info("test.cc", 167, "测试logger.hpp相关操作");
//     // std::cout << "logger->warn() before" << std::endl;
//     logger->warn("test.cc", 167, "测试logger.hpp相关操作");
//     // std::cout << "logger->warn() after" << std::endl;
//     logger->error("test.cc", 167, "测试logger.hpp相关操作");
//     logger->fatal("test.cc", 167, "测试logger.hpp相关操作");

//     for(int i = 0; i < 300000; ++i)
//     {
//         logger->fatal(__FILE__, __LINE__, "测试logger.hpp相关操作 %d", i);
//     }

//     return 0;
// }




// 测试buffer.hpp相关操作

// int main()
// {
//     std::ifstream ifs;
//     ifs.open("./logfiles/specificFileSink.log", std::ios::binary | std::ios::in);
//     if(!ifs.is_open())
//     {
//         std::cout << "ifs.open error" << std::endl;
//         return -1;
//     }
    
//     ifs.seekg(0, std::ios::end);
//     int len = ifs.tellg();
//     ifs.seekg(0, std::ios::beg);
//     std::cout << "len: " << len << std::endl;

//     snowdragon::Buffer buff;
//     std::cout << "Buffer object create" << std::endl;

//     std::string str;
//     str.resize(len);
//     ifs.read(&str[0], len);
//     if(!ifs.good())
//     {
//         std::cout << "ifs.read error" << std::endl;
//         return -1;
//     }
//     std::cout << "ifs.read success" << std::endl;

//     // buff.push(str.c_str(), len);
//     // std::cout << "buff.push" << std::endl;
//     for(int i = 0; i < len; ++i)
//         buff.push(&str[i], 1);

//     std::ofstream ofs;
//     ofs.open("./logfiles/buffTest.log", std::ios::binary | std::ios::out);
//     if(!ofs.is_open())
//     {
//         std::cout << "ofs.open error" << std::endl;
//         return -1;
//     }
//     for(int i = 0; i < len; ++i)
//     {
//         ofs.write(buff.begin(), 1);
//         buff.pop(1);
//     }
    
//     return 0;
// }




// 测试UNSAFE_ASYNC_LOOPER

int main()
{
    snowdragon::LocalLoggerBuilder llb;
    llb.buildLoggerName("asynchronous");
    llb.buildLoggerType(snowdragon::Logger::LoggerType::ASYNC_LOGGER);

    llb.buildLoggerLevel(snowdragon::LogLevel::Level::DEBUG);
    llb.buildLoggerSink<snowdragon::specificFileSink>("./logfiles/asynchronous_unsafe_test.log");
    llb.buildLoggerSink<snowdragon::StdOutSink>();
    snowdragon::Logger::ptr logger = llb.build();
    logger->modifyAsyncLoggerAndLooperSafeType(snowdragon::AsyncLooperSafeType::UNSAFE_ASYNC_LOOPER);
    snowdragon::LoggerManager::getInstance().pushLogger(logger);

    for(int i = 0; i < 3000000; ++i)
    {
        logger->fatal("测试UNSAFE_ASYNC_LOOPER %d", i);
    }

    return 0;
}